<template>
    <div>
      <!-- 孙组件模板 -->
      <h3>孙组件</h3>
      <div>
        <p>孙组件可以直接注入祖父组件提供的数据：</p>
        <p>消息: {{ message }}</p>
        <p>计数: {{ count }}</p>
        <p>用户: {{ user.name }} ({{ user.age }} 岁)</p>
        <div class="controls">
          <button @click="incrementCount">增加计数</button>
        </div>
      </div>
    </div>
  </template>
  
  <script lang="ts" setup>
  /**
   * Provide/Inject 详解 - 后代组件(孙组件)
   * 
   * 1. 深层注入：
   *    - 后代组件可以注入任何祖先组件提供的数据
   *    - 注入时会从当前组件开始向上查找，直到找到对应的提供者
   * 
   * 2. 注入来源：
   *    - 数据来自最近的提供该数据的祖先组件
   *    - 如果多个祖先提供同名数据，则使用最近的那个
   */
  
  import { inject } from 'vue';
  
  // 直接从祖父组件注入数据，跳过父组件
  // const message = inject('message');
  // 如果祖先组件没有提供该数据，使用默认值
  const message = inject('message', '默认消息');
  const count = inject('count', 0);
  const user = inject('user', { name: '默认用户', age: 20 });
  
  // 注入祖父组件提供的方法
  const increment = inject('increment', () => {});
  
  // 使用注入的方法更新祖父组件数据
  function incrementCount() {
    increment();
  }
  
  /**
   * 3. Provide/Inject 的优缺点：
   * 
   * 优点：
   * - 避免 props 逐层传递（prop drilling）
   * - 适合应用级别的共享数据
   * - 组件之间的耦合度低于直接的 props 传递
   * 
   * 缺点：
   * - 使组件之间产生隐式依赖，可能难以追踪数据来源
   * - 重构时可能导致意外破坏依赖关系
   * - 过度使用会使应用状态管理变得混乱
   * 
   * 4. 与其他通信方式的对比：
   *    - Props/Events: 适用于父子组件之间的直接通信
   *    - Vuex/Pinia: 适用于全局状态管理，有更完善的状态追踪
   *    - Provide/Inject: 适用于组件树中深层组件的数据共享
   * 
   * 5. 最佳实践：
   *    5.1 为提供的数据使用明确的命名，避免冲突
   *    5.2 使用 TypeScript 类型增强类型安全
   *    5.3 考虑使用 Symbol 作为 key 避免命名冲突
   *    5.4 文档化组件提供和注入的数据
   *    5.5 对于应用级别的状态，考虑使用 Pinia 代替
   */
  </script>
  
  <style scoped>
  /* 孙组件样式 */
  div {
    background: linear-gradient(to right, #43cea2, #185a9d);
    border-radius: 12px;
    padding: 20px;
    margin: 15px 0;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
  }
  
  div:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
  }
  
  h3 {
    color: #ffffff;
    font-size: 22px;
    margin-bottom: 15px;
    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
    font-weight: 500;
    letter-spacing: 1px;
  }

  p {
    margin: 8px 0;
    color: white;
  }

  .controls {
    margin: 15px 0;
  }

  button {
    background-color: white;
    color: #185a9d;
    border: none;
    padding: 8px 15px;
    border-radius: 6px;
    font-weight: bold;
    cursor: pointer;
    transition: all 0.2s;
  }

  button:hover {
    background-color: #185a9d;
    color: white;
    transform: translateY(-2px);
  }
  </style>